﻿using System;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
//using CrystalDecisions.CrystalReports.Engine;
//using CrystalDecisions.Shared;
//using CrystalDecisions.Web;
using POSGui.Clases.Entities;
using POSGui.Classes.BusinessLogic;

namespace POSGui.Presentacion
{
    public partial class Pagos : Page
    {
        private Sale _currentSale;
        private SaleStatus[] _saleStatuses;
        WebServiceAgent userAgent;

        protected void Page_Load(object sender, EventArgs e)
        {
            //.. Codigo de verificacion de exiracion 
            Response.Cache.SetCacheability(HttpCacheability.NoCache);
            Response.Cache.SetExpires(DateTime.Now.AddSeconds(-1));
            Response.Cache.SetNoStore();
            Response.AppendHeader("Pragma", "no-cache");
            if (Page.IsPostBack)
            {
                if (IsPageExpired())
                {
                    Response.Redirect(Constants.PAGE_MENU, true);
                    return;
                }
                Session["TimeStamp"] = DateTime.Now.ToString();
                ViewState["TimeStamp"] = DateTime.Now.ToString();
            }
            //..................

            userAgent = (WebServiceAgent)Session[Constants.USER_WEB_SERVICE_CONN];
            var sale = CartManager.GetInstance(userAgent)._currentSale;
            if (sale == null)
            {
                //TODO: Regresar a ventas
                Response.Redirect(Constants.PAGE_MENU,true);
                return;
            }

            _currentSale = (Sale)sale;
            SetSale();                       
        }



        /// <summary>
        /// Metodo q permite saber si una pagina expiró o no
        /// </summary>
        /// <returns></returns>
        private bool IsPageExpired()
        {
            if (Session["TimeStamp"] == null ||
               ViewState["TimeStamp"] == null)
                return false;
            return Session["TimeStamp"] == ViewState["TimeStamp"];
        }


        #region Métodos que actualizan el GUI

        /// <summary>
        /// Método que prepara la venta
        /// </summary>
        private void SetSale()
        {
            TotalTexto.Text = string.Format("{0:0.00}", _currentSale.Balance + (_currentSale.Balance * Constants.SALE_TAX));
        }

        /// <summary>
        /// Método que actualiza el GUI para la opcion de Efectivo
        /// </summary>
        private void SetCash()
        {
            FilaEfectivo.Visible = true;
            FilaTarjeta.Visible = false;
            FilaDiferencia.Visible = true;
            FilaCodigoTarjeta.Visible = false;
            FilaVencimientoTarjeta.Visible = false;
            FilaNumeroTarjeta.Visible = false;
            FilaNombreTarjeta.Visible = false;
            EfectivoText.Text = "";            
        }


        /// <summary>
        /// Método que actualiza el GUI para la opcion de Tarjeta
        /// </summary>
        private void SetCard()
        {
            FilaEfectivo.Visible = false;
            FilaTarjeta.Visible = true;
            FilaDiferencia.Visible = false;
            TarjetaText.Visible = true;
            TarjetaTextMixto.Visible = false;
            FilaCodigoTarjeta.Visible = true;
            FilaVencimientoTarjeta.Visible = true;
            FilaNumeroTarjeta.Visible = true;
            FilaNombreTarjeta.Visible = true;
            TarjetaText.Text = TotalTexto.Text;
        }

        /// <summary>
        /// Método que actualiza el GUI para la opcion de Mixto
        /// </summary>
        private void SetBoth()
        {
            FilaEfectivo.Visible = true;
            FilaTarjeta.Visible = true;
            FilaDiferencia.Visible = false;
            TarjetaText.Visible = false;
            TarjetaTextMixto.Visible = true;
            FilaCodigoTarjeta.Visible = true;
            FilaVencimientoTarjeta.Visible = true;
            FilaNumeroTarjeta.Visible = true;
            FilaNombreTarjeta.Visible = true;
            TarjetaText.Text = "";
            EfectivoText.Text = "";
        }

        #endregion

        #region Metodos de eventos del GUI

        /// <summary>
        /// Método que se dispara cuando se cambia el tipo de pago,
        /// actualiza las filas necesarias para el tipo de cambio seleccionado.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void TypeOfPaymentChange(object sender, EventArgs e)
        {
            string tipoDePago = ListaTipoDePago.SelectedValue;
            switch (tipoDePago)
            {
                case Constants.PAYMENT_CASH:
                    SetCash();
                    break;
                case Constants.PAYMENT_CARD:
                    SetCard();
                    break;
                case Constants.PAYMENT_BOTH:
                    SetBoth();
                    break;
            }
        }

        /// <summary>
        /// Método que se dispara cuando se presiona el botón de pagar.
        /// Marca la venta como finalizada y cancela el saldo de la venta.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Pagar(object sender, EventArgs e)
        {
            string tipoDePago = ListaTipoDePago.SelectedValue;

            switch (tipoDePago)
            {
                case Constants.PAYMENT_CASH:
                    _currentSale.PayMethod = Constants.PAYMENT_CASH;
                    GeneralPayment();
                    //ExecutePayment();
                    break;
                case Constants.PAYMENT_CARD:
                    _currentSale.PayMethod = Constants.PAYMENT_CARD;
                    //GeneralPayment();
                    CardPayment();
                    break;
                case Constants.PAYMENT_BOTH:
                    _currentSale.PayMethod = Constants.PAYMENT_BOTH;
                    GeneralPayment();
                    //CardValidation();
                    break;
            }
        }

        #endregion

        #region Métodos para consolidar el pago

        /// <summary>
        /// Método que se dispara cuando se presiona el botón de pagar.
        /// Marca la venta como finalizada y cancela el saldo de la venta.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void AcceptManualAutorization(object sender, EventArgs e)
        {
            /*var valuefromSession = GetValuefromSession(Constants.CREDIT_CARD_VAR);
            Card tarjeta = null;
            if (valuefromSession == null)
            {
                CardPayment();
            }
            else
            {
                tarjeta = (Card)valuefromSession;
                tarjeta.AutorizationCode = TextboxAutorizacion.Text;
                _webserviceWrapper.PaySaleWithCreditCard(tarjeta, _currentSale);
                PrintReceipt();
            }*/
        }


        /// <summary>
        /// Método que valida la tarjeta
        /// </summary>
        private void CardPayment()
        {
            /*try
            {
                var numeroTarjeta = Convert.ToInt64(NumeroTarjetaText.Text);
                var nombreTarjeta = NombreTarjetaText.Text;
                var codigoTarjeta = Convert.ToInt32(CodigoTarjetaText.Text);
                var vencimientoTarjetaMonth = Convert.ToInt32(VencimientoText.Text.Substring(0, 2));
                var vencimientoTarjetaYear = Convert.ToInt32(VencimientoText.Text.Substring(3, 2));
                var vencimientoTarjeta = new DateTime(vencimientoTarjetaYear, vencimientoTarjetaMonth, 1);
                var tarjeta = new Card
                                   {
                                       CardNumber = numeroTarjeta,
                                       HolderName = nombreTarjeta,
                                       SecurityCode = codigoTarjeta,
                                       ValidThrough = vencimientoTarjeta
                                   };
                StoreValuetoSession(Constants.CREDIT_CARD_VAR, tarjeta);
                var respuesta = _webserviceWrapper.ValidateCreditCard(tarjeta);
                if (respuesta.ResultOfOperation)
                {
                    var valid = (bool)respuesta.ResultObject;
                    if (valid)
                    {
                        _webserviceWrapper.PaySaleWithCreditCard(tarjeta, _currentSale);
                        PrintReceipt();
                    }
                    else
                    {
                        //MensajePopUp.Show();
                        ShowConfirmationMessage(Constants.ERROR_NOT_AUTORIZED, "Error de autorización", "AcceptManualAutorization");
                    }
                }
                else
                {
                    ShowAlertMessage(Constants.SYSTEM_NOT_AVAILABLE, Constants.SYSTEM_NOT_AVAILABLE_TITLE, "");
                }
            }
            catch (Exception)
            {
                ShowAlertMessage("Se produjo un error en la validación, por favor intente nuevamente", "Error de validación", "");
            }*/
        }

        /// <summary>
        /// Método que se encarga de realizar el pago general
        /// </summary>
        private void GeneralPayment()
        {
            bool result = CartManager.GetInstance(userAgent).CheckOut(userAgent, 3); //3 es colones
            if (result)
            {
                //PrintReceipt();
            }
            else
            {
                ShowAlertMessage(Constants.ERROR_NOTIFICATION, Constants.ERROR_NOTIFICATION_TITLE, "");            
            }
        }

        /// <summary>
        /// Método que actualiza la venta como finalizada al terminar el pago
        /// </summary>
        private void PrintReceipt()
        {
            CreateReceipt();
        }

        #endregion

        #region Métodos para imprimir factura


        protected void CreateReceiptEvent(object sender, EventArgs e)
        {
            CreateReceipt();
        }

        /// <summary>
        /// Metodo que permite crear el recibo
        /// </summary>
        private void CreateReceipt()
        {
            //ReceiptSource.Report.FileName = "..\\Reports\\Receipt.rpt";
            SetDbLogonInfo();
            // Se añaden los parametros
            //ReceiptSource.ReportDocument.SetParameterValue("idVenta", _currentSale.SaleId);
            _currentSale.SaleStatus = _saleStatuses.ToList().Find(status => status.Status == Constants.STATUS_FINISHED);
            StoreValuetoSession(Constants.CURRENT_SALE_VAR, _currentSale);
            //ReceiptSource.ReportDocument.ExportToHttpResponse(ExportFormatType.PortableDocFormat, Response, false, string.Format("{0}.pdf",_currentSale.SaleId));
        }


        /// <summary>
        /// Metodo que permite asignar los datos de la conexion
        /// </summary>
        private void SetDbLogonInfo()
        {
            try
            {
                //TableLogOnInfo login;
                /*foreach (Table table in ReceiptSource.ReportDocument.Database.Tables)
                {
                    /*login = table.LogOnInfo;
                    login.ConnectionInfo.ServerName = AppConfigReader.GetInstance().GetProperty("CrystalServer");
                    login.ConnectionInfo.DatabaseName = AppConfigReader.GetInstance().GetProperty("CrystalDataBase");
                    login.ConnectionInfo.UserID = AppConfigReader.GetInstance().GetProperty("CrystalUser");
                    login.ConnectionInfo.Password = AppConfigReader.GetInstance().GetProperty("CrystalPassword");
                    table.ApplyLogOnInfo(login);*/
                //}
            }
            catch (Exception)
            {
            }
        }


        #endregion

        #region Misc Methods




        /// <summary>
        /// Metodo que permite mostrar una alerta al usuario en la aplicacion
        /// </summary>
        /// <param name="message">Mensaje a mostrar</param>
        /// <param name="title">Titulo a mostrar</param>
        /// <param name="eventName">Nombre de evento por asignar al boton de ok</param>
        private void ShowAlertMessage(string message, string title, string eventName)
        {
            ShowPopUpMessage(message, title, "Aceptar", "", eventName, false);
        }


        /// <summary>
        /// Metodo que permite mostrar un mensaje de confirmacion al usuario en la aplicacion
        /// </summary>
        /// <param name="message">Mensaje a mostrar</param>
        /// <param name="title">Titulo a mostrar</param>
        /// <param name="eventName">Nombre de evento por asignar al boton de ok</param>
        private void ShowConfirmationMessage(string message, string title, string eventName)
        {
            ShowPopUpMessage(message, title, "Aceptar", "Cancelar", eventName, true);
        }

        /// <summary>
        /// Metodo que permite mostrar un mensaje de confirmacion al cliente
        /// </summary>
        /// <param name="message">Mensaje a mostrar</param>
        /// <param name="title">Titulo a mostrar</param>
        /// <param name="okLabel"></param>
        /// <param name="cancelLabel"></param>
        /// <param name="eventName">Nombre de evento por asignar al boton de ok</param>
        /// <param name="confirmation">Permite escoger entre mostrar el boton de cancelar o no</param>
        protected void ShowPopUpMessage(string message, string title, string okLabel, string cancelLabel, string eventName, bool confirmation)
        {
            LabelTitulo.Text = title;
            LabelMensaje.Text = message;
            btnOkPopUp.Text = okLabel;
            btnClosePopUp.Text = cancelLabel;
            btnOkPopUp.Attributes.Remove("OnClick");
            if (!string.IsNullOrEmpty(eventName))
            {
                btnOkPopUp.Attributes.Add("OnClick", eventName);
                btnOkPopUp.UseSubmitBehavior = false;
            }
            else
            {
                btnOkPopUp.UseSubmitBehavior = true;
                btnOkPopUp.OnClientClick = "return hideModalPopupViaClient();";
            }
            btnClosePopUp.Visible = confirmation;
            TextboxAutorizacion.Visible = confirmation;
            MensajePopUp.Show();

        }

        /// <summary>
        /// Metodo que permite ingresar un valor a la sesion
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        private void StoreValuetoSession(string key, object value)
        {
            Session[key + GetSessionUser()] = value;
        }


        /// <summary>
        /// Metodo que permite obtener un valor de la sesion
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private Object GetValuefromSession(string key)
        {
            return Session[key + GetSessionUser()];
        }

        /// <summary>
        /// Metodo que permite obtener la session actual
        /// </summary>
        /// <returns>String con el identificador de la session actual</returns>
        private String GetSessionUser()
        {
            var cookie = Request.Cookies.Get(FormsAuthentication.FormsCookieName);
            if (cookie == null)
            {
                return null;
            }
            var decrypted = FormsAuthentication.Decrypt(cookie.Value);
            return decrypted.UserData;
        }
        #endregion
    }
}